import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:game_11_sleep_game12/file.dart';
import 'package:game_11_sleep_game12/main.dart';
import 'package:game_11_sleep_game12/menu.dart';
import 'package:game_11_sleep_game12/music_player.dart';
import 'package:game_11_sleep_game12/rank.dart';
import 'tile.dart';

double tile_width_data = 80;
double tile_height_data = 85;

double h_s = tile_width_data * 0.5;
double v_s = tile_height_data * 0.5;

Offset screen_offset = Offset(50, 200);
Offset save_offset = Offset(50, screen_height - 2 * tile_height_data);

bool music_flag = true;
int tu = 0;
int time_count = 0;
bool dl_flag = false;
int key_number = 0;

void clear_all() {
  music_flag = true;
  tu = 0;
  time_count = 0;
}

List<Tile> tile_list_01 = [];
List<Tile> tile_list_02 = [];
List<Tile> tile_list_03 = [];
List<Tile> tile_list_04 = [];
List<Tile> save_tile_list = [];
List<Tile> select_tile_list = [];
List<Tile> a_t_l = [];
List<List<Tile>> game_tile_list = [];
List<List<Tile>> save_tile_list_copy = [];

void init_data() {
  dl_flag = false;
  tile_list_01 = [];
  tile_list_02 = [];
  tile_list_03 = [];
  tile_list_04 = [];
  save_tile_list = [];
  select_tile_list = [];
  a_t_l = [];
  game_tile_list = [];
  save_tile_list_copy = [];
  insert_value();
  shuffle_list();
}

void insert_value() {
  key_number = DateTime.now().microsecond;
  if (tu == 0) {
    h_s = tile_width_data * 0.5;
    v_s = tile_height_data * 0.5;
    int width_data = 3;
    tile_list_01 = List.generate(
      width_data * width_data,
      (i) {
        double total_width = (h_s + tile_width_data) * width_data;
        double total_height = (v_s + tile_height_data) * width_data;

        double dx = screen_width / 2 - total_width / 2;
        double dy = screen_height / 2 - total_height / 2;

        int row = i ~/ width_data;
        int col = i % width_data;

        Rect rect = Rect.fromLTWH(
            dx + (h_s + tile_width_data) * col,
            dy + (v_s + tile_height_data) * row,
            tile_width_data,
            tile_height_data);

        return Tile(key_number++, rect, rect,
            image_id: col, level: 0, angle: Random().nextDouble() * 360);
      },
    );
    tile_list_02 = List.generate(
      width_data * width_data,
      (i) {
        double total_width = (h_s + tile_width_data) * width_data;
        double total_height = (v_s + tile_height_data) * width_data;

        double dx = screen_width / 2 - total_width / 2;
        double dy = screen_height / 2 - total_height / 2;

        int row = i ~/ width_data;
        int col = i % width_data;

        Rect rect = Rect.fromLTWH(
            dx + (h_s + tile_width_data) * col,
            30 + dy + (v_s + tile_height_data) * row,
            tile_width_data,
            tile_height_data);

        return Tile(key_number++, rect, rect,
            image_id: col, level: 1, angle: Random().nextDouble() * 360);
      },
    );

    game_tile_list = [
      tile_list_01,
      tile_list_02,
    ];
  } else {
    h_s = v_s = 1;
    int width_data = 6;
    tile_list_01 = List.generate(
      width_data * width_data,
      (i) {
        double total_width = (h_s + tile_width_data) * width_data;
        double total_height = (v_s + tile_height_data) * width_data;

        double dx = screen_width / 2 - total_width / 2;
        double dy = screen_height / 2 - total_height / 2;

        int row = i ~/ width_data;
        int col = i % width_data;

        Rect rect = Rect.fromLTWH(
            dx + (h_s + tile_width_data) * col,
            dy + (v_s + tile_height_data) * row,
            tile_width_data,
            tile_height_data);

        return Tile(key_number++, rect, rect,
            image_id: col, level: 0, angle: Random().nextDouble() * 360);
      },
    );
    width_data = 5;
    tile_list_02 = List.generate(
      width_data * width_data,
      (i) {
        double total_width = (h_s + tile_width_data) * width_data;
        double total_height = (v_s + tile_height_data) * width_data;

        double dx = screen_width / 2 - total_width / 2;
        double dy = screen_height / 2 - total_height / 2;

        int row = i ~/ width_data;
        int col = i % width_data;

        Rect rect = Rect.fromLTWH(
            dx + (h_s + tile_width_data) * col,
            dy + (v_s + tile_height_data) * row,
            tile_width_data,
            tile_height_data);

        return Tile(key_number++, rect, rect,
            image_id: col, level: 1, angle: Random().nextDouble() * 360);
      },
    );
    width_data = 4;
    tile_list_03 = List.generate(
      width_data * width_data,
      (i) {
        double total_width = (h_s + tile_width_data) * width_data;
        double total_height = (v_s + tile_height_data) * width_data;

        double dx = screen_width / 2 - total_width / 2;
        double dy = screen_height / 2 - total_height / 2;

        int row = i ~/ width_data;
        int col = i % width_data;

        Rect rect = Rect.fromLTWH(
            dx + (h_s + tile_width_data) * col,
            dy + (v_s + tile_height_data) * row,
            tile_width_data,
            tile_height_data);

        return Tile(key_number++, rect, rect,
            image_id: col, level: 2, angle: Random().nextDouble() * 360);
      },
    );
    width_data = 1;
    tile_list_04 = List.generate(
      width_data * width_data,
      (i) {
        double total_width = (h_s + tile_width_data) * width_data;
        double total_height = (v_s + tile_height_data) * width_data;

        double dx = screen_width / 2 - total_width / 2;
        double dy = screen_height / 2 - total_height / 2;

        int row = i ~/ width_data;
        int col = i % width_data;

        Rect rect = Rect.fromLTWH(
            dx + (h_s + tile_width_data) * col,
            dy + (v_s + tile_height_data) * row,
            tile_width_data,
            tile_height_data);

        return Tile(key_number++, rect, rect,
            image_id: 4, level: 3, angle: Random().nextDouble() * 360);
      },
    );
    game_tile_list = [
      tile_list_01,
      tile_list_02,
      tile_list_03,
      tile_list_04,
    ];
  }
}

void shuffle_list() {
  int index = 0;
  List<List<int>> l = List.generate(
      game_tile_list.length,
      (i) => List.generate(
          game_tile_list[i].length, (j) => game_tile_list[i][j].image_id));
  List<int> id_list = l.expand((element) => element).toList();
  id_list.shuffle();
  for (int i = 0; i < game_tile_list.length; i++) {
    for (int j = 0; j < game_tile_list[i].length; j++) {
      game_tile_list[i][j].image_id = id_list[index++];
    }
  }
}

class game_home extends StatefulWidget {
  const game_home({super.key});

  @override
  State<game_home> createState() => _game_homeState();
}

class _game_homeState extends State<game_home> with TickerProviderStateMixin {
  late Timer pz_timer;
  late Timer time_timer;
  late Timer dl_timer;

  void pz() {
    for (int i = 0; i < tile_list_01.length; i++) {
      tile_list_01[i].show_flag = true;
      for (int j = 0; j < tile_list_02.length; j++) {
        if (tile_list_01[i].new_rect.overlaps(tile_list_02[j].new_rect)) {
          tile_list_01[i].show_flag = false;
        }
      }
    }

    for (int i = 0; i < tile_list_02.length; i++) {
      tile_list_02[i].show_flag = true;
      for (int j = 0; j < tile_list_03.length; j++) {
        if (tile_list_02[i].new_rect.overlaps(tile_list_03[j].new_rect)) {
          tile_list_02[i].show_flag = false;
        }
      }
    }

    for (int i = 0; i < tile_list_03.length; i++) {
      tile_list_03[i].show_flag = true;
      for (int j = 0; j < tile_list_04.length; j++) {
        if (tile_list_03[i].new_rect.overlaps(tile_list_04[j].new_rect)) {
          tile_list_03[i].show_flag = false;
        }
      }
    }

    setState(() {});
  }

  void init_controller() {
    for (int i = 0; i < game_tile_list.length; i++) {
      for (int j = 0; j < game_tile_list[i].length; j++) {
        game_tile_list[i][j].clear_controller = AnimationController(
            vsync: this, duration: Duration(milliseconds: 250));
        game_tile_list[i][j].scale_controller = AnimationController(
            vsync: this,
            duration: Duration(milliseconds: 250),
            lowerBound: 1.0,
            upperBound: 1.3);
        game_tile_list[i][j].clear_animation = Tween(begin: 1.0, end: 0.0)
            .animate(game_tile_list[i][j].clear_controller);
      }
    }
    setState(() {});
  }

  void init_data_all() {
    init_data();
    init_controller();
    setState(() {});
  }

  void start_timer() {
    pz_timer = Timer.periodic(Duration(milliseconds: 1000 ~/ 60), (timer) {
      pz();
      setState(() {});
    });
    time_timer = Timer.periodic(Duration(seconds: 1), (timer) {
      time_count += 1;
      setState(() {});
    });
  }

  void stop_timer() {
    pz_timer.cancel();
    time_timer.cancel();
  }

  void start_music() {
    MusicPlayer.play(music_id_01);
  }

  void stop_music() {
    MusicPlayer.stop(music_id_01);
  }

  @override
  void initState() {
    // TODO: implement initState
    init_data_all();
    start_timer();
    start_music();
    super.initState();
  }

  @override
  void dispose() {
    // TODO: implement dispose
    stop_music();
    stop_timer();
    super.dispose();
  }

  void update_save_tile() {
    for (int i = 0; i < save_tile_list.length; i++) {
      save_tile_list[i].new_rect = Rect.fromLTWH(
          85 + save_offset.dx + (tile_width_data + 10) * i,
          save_offset.dy + 20,
          tile_width_data,
          tile_height_data);
    }
    setState(() {});
  }

  add_clear_controller(Tile tile) {
    a_t_l = [];
    int count = 0;
    save_tile_list.forEach((element) {
      if (element.image_id == tile.image_id) {
        count += 1;
      }
    });
    if (count >= 3) {
      save_tile_list.forEach((element) {
        if (element.image_id == tile.image_id) {
          element.clear_controller.forward(from: 0);
          a_t_l.add(element);
        }
      });
      setState(() {});
      return true;
    }
    setState(() {});
    return false;
  }

  clear_save_tile_list(Tile tile) async {
    save_tile_list.removeWhere((element) => element.image_id == tile.image_id);
    await Future.delayed(Duration(milliseconds: 250));
    a_t_l = [];
    setState(() {});
  }

  void yc() {
    while (save_tile_list.isNotEmpty) {
      Tile last_tile = save_tile_list.last;
      last_tile.new_rect = last_tile.old_rect;
      game_tile_list[last_tile.level].add(last_tile.tile_copy);
      game_tile_list[last_tile.level].sort((a, b) => a.key - b.key);
      save_tile_list.removeLast();
    }
    update_save_tile();
    select_tile_list = [];
    save_tile_list_copy = [];
    setState(() {});
  }

  void ch() {
    if (select_tile_list.isNotEmpty) {
      Tile last_tile = select_tile_list.last;
      last_tile.new_rect = last_tile.old_rect;
      game_tile_list[last_tile.level].add(last_tile.tile_copy);
      game_tile_list[last_tile.level].sort((a, b) => a.key - b.key);
      save_tile_list_copy.removeLast();
      if (save_tile_list_copy.isNotEmpty) {
        save_tile_list = List.from(save_tile_list_copy.last);
      } else {
        save_tile_list = [];
      }
      select_tile_list.removeLast();
    }
    update_save_tile();
    setState(() {});
  }

  void xp() {
    dl_flag = true;
    Future.delayed(Duration(seconds: 2)).then((value) {
      dl_timer.cancel();
      dl_flag = false;
      for (int i = 0; i < game_tile_list.length; i++) {
        for (int j = 0; j < game_tile_list[i].length; j++) {
          game_tile_list[i][j].new_rect = game_tile_list[i][j].old_rect;
        }
      }
      shuffle_list();
    });

    dl_timer = Timer.periodic(Duration(milliseconds: 1000 ~/ 60), (timer) {
      for (int i = 0; i < game_tile_list.length; i++) {
        for (int j = 0; j < game_tile_list[i].length; j++) {
          game_tile_list[i][j].angle += game_tile_list[i][j].speed;
          double dx = center.dx +
              (tile_width_data * 2.5) * cos(game_tile_list[i][j].angle);
          double dy = center.dy +
              (tile_height_data * 2.5) * sin(game_tile_list[i][j].angle);
          game_tile_list[i][j].new_rect =
              Rect.fromLTWH(dx, dy, tile_width_data, tile_height_data);
        }
      }
      shuffle_list();
      setState(() {});
    });
  }

  game_over() {
    if (tu == 0 && game_tile_list.every((element) => element.isEmpty)) {
      tu = 1;
      init_data_all();
    }
    if (tu == 1 && game_tile_list.every((element) => element.isEmpty)) {
      save_rank_file(game_name, time_count, true);
      show_game_over("游戏胜利");
    }
    if (save_tile_list.length >= 7) {
      save_rank_file(game_name, time_count, false);
      show_game_over("游戏失败");
    }
  }

  show_game_over(String text) {
    stop_timer();
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text("${text}"),
            ],
          ),
          actions: [
            ElevatedButton(
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => menu_home()));
                clear_all();
                stop_music();
              },
              child: Text("返回首页"),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => rank_home()));
                clear_all();
                stop_music();
              },
              child: Text("排行榜"),
            ),
          ],
        );
      },
    );
  }

  show_return_page() {
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Text("是否确定离开本次游戏"),
            ],
          ),
          actions: [
            ElevatedButton(
              onPressed: () {
                Navigator.push(context,
                    MaterialPageRoute(builder: (context) => menu_home()));
                clear_all();
                stop_music();
              },
              child: Text("返回首页"),
            ),
            ElevatedButton(
              onPressed: () {
                Navigator.pop(context);
                start_timer();
              },
              child: Text("返回游戏"),
            ),
          ],
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                fit: BoxFit.cover,
                image: AssetImage("images/bg.jpeg"),
              ),
            ),
          ),
          WillPopScope(
            child: SizedBox(),
            onWillPop: () {
              return show_return_page();
            },
          ),
          Column(
            children: [
              SizedBox(
                height: 24,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  Container(
                    width: 120,
                    height: 120,
                    color: Colors.cyan,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Text('玩家名'),
                        Text("${game_name}"),
                      ],
                    ),
                  ),
                  Container(
                    width: 120,
                    height: 120,
                    color: Colors.cyan,
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                      children: [
                        Text('时间'),
                        Text(
                            "${time_count ~/ 3600}:${(time_count % 3600) ~/ 60}:${time_count % 60}"),
                      ],
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      yc();
                      setState(() {});
                    },
                    child: Container(
                      width: 120,
                      height: 120,
                      color: Colors.cyan,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          Text('移出'),
                        ],
                      ),
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      ch();
                      setState(() {});
                    },
                    child: Container(
                      width: 120,
                      height: 120,
                      color: Colors.cyan,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          Text('撤回'),
                        ],
                      ),
                    ),
                  ),
                  InkWell(
                    onTap: () {
                      xp();
                      setState(() {});
                    },
                    child: Container(
                      width: 120,
                      height: 120,
                      color: Colors.cyan,
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          Text('洗牌'),
                        ],
                      ),
                    ),
                  ),
                  IconButton(
                    onPressed: () async {
                      music_flag = !music_flag;
                      if (music_flag) {
                        await lead_music();
                        start_music();
                      } else {
                        stop_music();
                      }
                      setState(() {});
                    },
                    icon: Icon(music_flag ? Icons.music_note : Icons.music_off),
                  ),
                ],
              ),
            ],
          ),
          // Positioned(
          //   left: screen_offset.dx,
          //   top: screen_offset.dy,
          //   child: Container(
          //     width: screen_width - screen_offset.dx * 2,
          //     height: screen_height - screen_offset.dy * 2,
          //     color: Colors.cyan,
          //   ),
          // ),
          Positioned(
            left: save_offset.dx,
            top: save_offset.dy,
            child: Container(
              width: screen_width - save_offset.dx * 2,
              height: tile_height_data * 1.5,
              color: Colors.brown,
            ),
          ),
          for (int i = 0; i < game_tile_list.length; i++)
            for (int j = 0; j < game_tile_list[i].length; j++)
              if (game_tile_list[i][j].show_flag == false)
                AnimatedPositioned.fromRect(
                  key: ValueKey(game_tile_list[i][j].key),
                  rect: game_tile_list[i][j].new_rect,
                  duration: Duration(milliseconds: 250),
                  child: Container(
                    decoration: BoxDecoration(
                      color: dl_flag ? Colors.white : Colors.black54,
                      image: DecorationImage(
                        image: AssetImage("${game_tile_list[i][j].get_image}"),
                      ),
                    ),
                  ),
                ),
          for (int i = 0; i < game_tile_list.length; i++)
            for (int j = 0; j < game_tile_list[i].length; j++)
              if (game_tile_list[i][j].show_flag)
                AnimatedPositioned.fromRect(
                  key: ValueKey(game_tile_list[i][j].key),
                  rect: game_tile_list[i][j].new_rect,
                  duration: Duration(milliseconds: 250),
                  child: GestureDetector(
                    onLongPressEnd: (d) async {
                      game_tile_list[i][j].scale_controller.reset();
                      if (music_flag) {
                        MusicPlayer.play(music_id_03);
                      }
                      Tile tile = game_tile_list[i][j];
                      Tile tile_copy = tile.tile_copy;
                      int index = save_tile_list.lastIndexWhere(
                          (element) => element.image_id == tile.image_id);
                      if (index != -1) {
                        tile.new_rect = Rect.fromLTWH(
                            85 +
                                save_offset.dx +
                                (tile_width_data + 10) * (index + 1),
                            save_offset.dy + 20,
                            tile_width_data,
                            tile_height_data);
                        save_tile_list.insert(index + 1, tile_copy);
                      } else {
                        tile.new_rect = Rect.fromLTWH(
                            85 +
                                save_offset.dx +
                                (tile_width_data + 10) *
                                    (save_tile_list.length),
                            save_offset.dy + 20,
                            tile_width_data,
                            tile_height_data);
                        save_tile_list.add(tile_copy);
                      }
                      update_save_tile();
                      save_tile_list_copy.add(List.from(save_tile_list));
                      game_tile_list[tile.level]
                          .remove(game_tile_list[tile.level][j]);
                      await Future.delayed(Duration(milliseconds: 250));

                      bool clear_flag = await add_clear_controller(tile);
                      if (music_flag && clear_flag) {
                        MusicPlayer.play(music_id_02);
                      }
                      if (clear_flag) {
                        await clear_save_tile_list(tile);
                        update_save_tile();
                      }
                      select_tile_list.add(tile_copy);
                      game_over();
                      setState(() {});
                    },
                    onLongPress: () {
                      game_tile_list[i][j].scale_controller.forward(from: 0);
                      setState(() {});
                    },
                    onTap: () async {
                      game_tile_list[i][j].scale_controller.reset();
                      if (music_flag) {
                        MusicPlayer.play(music_id_03);
                      }
                      Tile tile = game_tile_list[i][j];
                      Tile tile_copy = tile.tile_copy;
                      int index = save_tile_list.lastIndexWhere(
                          (element) => element.image_id == tile.image_id);
                      if (index != -1) {
                        tile.new_rect = Rect.fromLTWH(
                            85 +
                                save_offset.dx +
                                (tile_width_data + 10) * (index + 1),
                            save_offset.dy + 20,
                            tile_width_data,
                            tile_height_data);
                        save_tile_list.insert(index + 1, tile_copy);
                      } else {
                        tile.new_rect = Rect.fromLTWH(
                            85 +
                                save_offset.dx +
                                (tile_width_data + 10) *
                                    (save_tile_list.length),
                            save_offset.dy + 20,
                            tile_width_data,
                            tile_height_data);
                        save_tile_list.add(tile_copy);
                      }
                      update_save_tile();
                      save_tile_list_copy.add(List.from(save_tile_list));
                      game_tile_list[tile.level]
                          .remove(game_tile_list[tile.level][j]);
                      await Future.delayed(Duration(milliseconds: 250));

                      bool clear_flag = await add_clear_controller(tile);
                      if (music_flag && clear_flag) {
                        MusicPlayer.play(music_id_02);
                      }
                      if (clear_flag) {
                        await clear_save_tile_list(tile);
                        update_save_tile();
                      }
                      select_tile_list.add(tile_copy);
                      game_over();
                      setState(() {});
                    },
                    child: ScaleTransition(
                      scale: game_tile_list[i][j].scale_controller,
                      child: Container(
                        decoration: BoxDecoration(
                          color: Colors.white,
                          image: DecorationImage(
                            image:
                                AssetImage("${game_tile_list[i][j].get_image}"),
                          ),
                        ),
                      ),
                    ),
                  ),
                ),
          for (int i = 0; i < save_tile_list.length; i++)
            AnimatedPositioned.fromRect(
              key: ValueKey(save_tile_list[i].key),
              rect: save_tile_list[i].new_rect,
              duration: Duration(milliseconds: 250),
              child: Container(
                decoration: BoxDecoration(
                  color: Colors.white,
                  image: DecorationImage(
                    image: AssetImage("${save_tile_list[i].get_image}"),
                  ),
                ),
              ),
            ),
          for (int i = 0; i < a_t_l.length; i++)
            AnimatedPositioned.fromRect(
              rect: a_t_l[i].new_rect,
              duration: Duration(milliseconds: 250),
              child: ScaleTransition(
                scale: a_t_l[i].clear_animation,
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    image: DecorationImage(
                      image: AssetImage("${a_t_l[i].get_image}"),
                    ),
                  ),
                ),
              ),
            ),
        ],
      ),
    );
  }
}
